-
Notifications
You must be signed in to change notification settings - Fork 43
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Compile variable features #635
Conversation
183d19a
to
737fffc
Compare
b794e7d
to
458ef3b
Compare
So to trigger this, a font project must make sure to have the same exact feature file text in every source, meaning that you have to use variable feature syntax if there are differences in some parts of the Designspace? |
@@ -92,6 +95,10 @@ def __init__(self, ufo, ttFont=None, glyphSet=None, **kwargs): | |||
|
|||
glyphOrder = ttFont.getGlyphOrder() | |||
if glyphSet is not None: | |||
if set(glyphOrder) != set(glyphSet.keys()): | |||
print("Glyph order incompatible") |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This should probably be a logger.error
. Also, the glyph set is being tested, not the order.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
this is just before an assert
so it doesn't matter much if we print
or do logger.error
, an AssertionError should never trigger and is not something client can expect to recover from. It's just the error message for the hard crash, it could be moved to the assert
optional string parameter, if you want.
Yes, it doesn’t attempt to do a text/AST-based merge of the feature files. At least not at this stage - maybe that can come later. I’m fairly sure that this will cover a good number of font projects, and those that it doesn’t get cover will get the old style merge. |
if compiler is not None: | ||
# The result is cached in the compiler instance, so if another | ||
# writer requests one it is not compiled again. | ||
if hasattr(compiler, "_gsub"): | ||
return compiler._gsub | ||
|
||
glyphOrder = compiler.ttFont.getGlyphOrder() | ||
fvar = compiler.ttFont.get("fvar") | ||
if fvar: | ||
feafile = copy.deepcopy(feafile) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Why the deepcopy?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
indeed, why?
In one of our fonts, this seems to drop some kerning pairs but not others (can't check if this is just the kern splitting because the font doesn't compile without this PR) 🤔 weird, drilling some more. Also, the Rules writer is not hooked up and justr dropping it into the default feature writer list doesn't seem to do anything. |
self._conditionsets.append(conditionset) | ||
else: | ||
cs_name = "ConditionSet%i" % self._conditionsets.index(conditionset) | ||
# XXX |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
?
So, I get rules to work when I graft the GSUB Notes:
|
I disabled the rules writer because varLib also handles designspace rules during the merge and I was ending up with them being emitted twice. |
Weird. For my test font, no GSUB variations are emitted without the rules writer. |
Now we do approximately what varLib is doing with rules, though compared to a reference, the numbers and lookups are off in some places. Maybe I use There still remains a difference in kern behavior I need to investigate. |
Also todo: The test should include disjoint kerning pairs for different scripts, to ensure we handle disjoint kerning in different masters correctly (i.e. Armenian only in one, Greek only in the other). |
Oh, I know what's going on. My test sources happen to trigger the compile-features-once-but-later code path, so varLib adds feature variations and then we overwrite them when running the feature writers. This also seems to affect kerning. |
Next, my test source has e.g. an |
You're using non-public test sources, which makes it difficult for other people to repro... I'll see what I can find. |
Note to self: |
Woops, yeah. I'll be back at work next week and can see if I can make a reproducer. For now, maybe just compile the font with identical features with 2.28.0 and then with this branch and compare kerning. I thought I turned ligature writing off? Should be in https://github.com/googlefonts/glyphsLib/releases/tag/v6.0.7 |
yeah, the GdefFeatureWriter in ufo2ft should handle both the GlyphClassDefs (using public.openTypeCategories in the ufo lib) and the LigatureCarets (from the glyph anchors named "caret_", "vcaret_") |
So, I tried to come up with a minimal reproducer, but so far, no luck. What did seem to work was to make a union of all kerning values over all sources, putting in missing ones as zero-kerns. The specific pair I was looking at was actually "missing" such a zero-kern in one corner of the design space. Maybe that's what's missing? |
varLib allows "sparse kerning", i.e. if Light and bold have a value but Regular doesn't, the value at Regular is interpolated rather than set to zero. So, filling in zero for missing kern pairs seems like the wrong thing to do. |
In my testing with a proprietary font, it seems the kerning is there, but it is not used, as if the shaper was stopping earlier. Subsetting the font to contain just the two glyphs I want to look at makes the kern work as expected. Will try to reproduce with an OSS font. |
Found an open font that repros: Roboto Serif with "py". |
Here is a very minimal reproducer: |
(The last commit should be using sets instead of lists for members in |
With your patch and fonttools/fonttools#2776, I think this is good now.
|
Ship it! :-) |
* Using this version of otRound allows us to reuse a lot more code * A couple of variable scalar / designspace utility functions * Allow compileGSUB to know about fvar tables
This is the same as a FeatureCompiler but it knows its designspace and it also loads the RulesFeatureWriter if there are any designspace rules
Add test for different feature writers Fix up test expectations This should now test the variable features
…ling variable features
7d06369
to
1f3f179
Compare
822c4b4
to
91e76cd
Compare
in googlefonts/ufo2ft#635 that symbol is no longer exported, better to import from its actual location
from ufo2ft.constants import INDIC_SCRIPTS, USE_SCRIPTS | ||
from ufo2ft.featureWriters import BaseFeatureWriter, ast | ||
from ufo2ft.util import ( | ||
classifyGlyphs, | ||
quantize, |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
@simoncozens I had to change glyphsLib's markFeatureWriter to import quantize
from ufo2ft.util
otherwise we get ImportError with this PR:
googlefonts/glyphsLib@ae08b26
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
oh I had forgotten that you already have a PR for that, sorry: googlefonts/glyphsLib#957
ok so we shall merge that one once we release this
this can be useful to debugging, comparing build time of new vs old build pipeline, or if one wants to ensure no binary changes occur when updating the compiler
@simoncozens hope you don't mind if I added a |
…OTL tables this is meant to work with googlefonts/ufo2ft#635
…OTL tables this is meant to work with googlefonts/ufo2ft#635
This is a work in progress. The idea is this: when we are compiling a variable font from designspace, most of the time the feature files are exactly the same; the only thing which differs is the "implicit" rules created from anchors and kerning. Currently we build each font independently, and this means we compile binary features N times (where N=number of masters), and then merge them at the end. When there are overflows, compiling binary features N times is slow. Instead, this PR holds off the compilation of GSUB/GPOS tables to the end, and uses "variable" feature writers which describe how the kerning and anchors vary across the designspace. i.e. instead of:
and compiles the features twice, it produces
and compiles the features once.
It's a lot faster.